
const { ccclass, property } = cc._decorator;
/**
 *
 * 使用例子，先给摄像机添加脚本 
  let camera = cc.find('Canvas/Main Camera');
  if (!camera.getComponent('CameraController')) {
      camera.addComponent('CameraController');
  }
  如果需要axisX跟随
  CameraController.followNode = {target}:cc.Node;
  线性插值地缩放摄像机
  CameraController.setCameraRatio({scale}:Number);
 */
@ccclass
export class CameraController extends cc.Component {

    isFollow: boolean = true;
    followNode: cc.Node = null;
    followOffset: cc.Vec2 = new cc.Vec2(0, 0);
    _worldDest: cc.Vec2 = null;
    get worldDest(): cc.Vec2 {
        return this._worldDest;
    }
    set worldDest(wpos: cc.Vec2) {
        if (!wpos) return;
        const winSize = cc.view.getVisibleSize();
        let width = winSize.width / winSize.height * (this.dstOrthoHeight * 2);
        let height = this.dstOrthoHeight * 2;
        let curRect = cc.rect(
            wpos.x - width / 2 + this.followOffset.x,
            wpos.y - height / 2 + this.followOffset.y,
            width,
            height
        )
        // console.log('wpos1', wpos)
        if (this.limitRect) {
            let limitRect = this.limitRect;
            // gameHelper.clearDraw();
            // gameHelper.drawAny(null, curRect, limitRect)
            if (curRect.x < limitRect.x) {
                // console.log('x', limitRect.x - curRect.x)
                wpos.x += (limitRect.x - curRect.x);
            }
            if (curRect.x + curRect.width > limitRect.x + limitRect.width) {
                // console.log('x2', (limitRect.x + limitRect.width) - (curRect.x + curRect.width))
                wpos.x += ((limitRect.x + limitRect.width) - (curRect.x + curRect.width));
            }
            if (curRect.y < limitRect.y) {
                // console.log('y', limitRect.y - curRect.y)
                wpos.y += (limitRect.y - curRect.y);
            }
            if (curRect.y + curRect.height > limitRect.y + limitRect.height) {
                // console.log('y2', (limitRect.y + limitRect.height) - (curRect.y + curRect.height))
                wpos.y += ((limitRect.y + limitRect.height) - (curRect.y + curRect.height));
            }
        }
        // console.log('wpos2', wpos)
        this._worldDest = wpos;
    }
    dstOrthoHeight: number = null;

    curCameraTween: cc.Tween = null;
    dt: number = null;
    cameraCmpt: cc.Camera = null;
    ctx: cc.Graphics = null;
    limitRect: cc.Rect = null;

    moveRaioMultiple = 15;
    shakeInterval: number = 0.02;
    shakeDist: number = 12;

    cameraRatio: number = 1;
    cameraDest: cc.Vec2 = cc.Vec2.ZERO;

    // 添加摄像机控制器
    // 添加摄像机控制器
    static get instance(): CameraController {
        let camera = cc.find('Canvas/Main Camera');
        if (!camera.getComponent(CameraController)) {
            camera.addComponent(CameraController);
        }
        return camera.getComponent(CameraController);
    }
    onLoad() {
        window['cameraCtrl'] = this;
        this.cameraCmpt = this.node.getComponent(cc.Camera);
        this.setCameraRatio(1)
    }

    // 是否在屏幕内
    isContainRect(rect: cc.Rect): boolean {
        let wpos = this.node.parent.convertToWorldSpaceAR(this.node.position);
        let thisRect = new cc.Rect(wpos.x - cc.winSize.width / 2, wpos.y - cc.winSize.height / 2, cc.winSize.width, cc.winSize.height)
        let res = thisRect.containsRect(rect);
        // console.log('res', res);
        // let ctx = GameHelper.getDebugSceneCtx()
        // ctx.clear();
        // ctx.rect(thisRect.x, thisRect.y, thisRect.width, thisRect.height);
        // ctx.stroke();
        return res;
    }
    // 设置相机的缩放度
    setDestOrthoHright(orthoHright: number): void {
        // this.dstOrthoHeight = orthoHright;
        this.cameraRatio = (cc.winSize.height / 2) / orthoHright;

    }
    // 设置相机的缩放度
    setCameraRatio(cameraRatio): void {
        this.cameraRatio = cameraRatio;
    }
    // 线性缩放
    private zoomCameraTo(): void {
        // console.log('zoomCameraTo')
        if (this.node && this.node.isValid && typeof this.cameraRatio == 'number') {
            let ratio = this.dt * 2;
            let cameraCmpt = this.node.getComponent(cc.Camera);
            cameraCmpt.zoomRatio += (this.cameraRatio - cameraCmpt.zoomRatio) * ratio;
        }
    }
    /**
     * 
     * @param node 跟随的节点
     * @param moveRaioMultiple 跟随的速率
     * @param offset 坐标偏移
     */
    // console.log('setFollowNode', node)
    setFollow(target: (Node | cc.Vec2), moveRaioMultiple: number, offset: cc.Vec2 = cc.v2(0, 0), limitRect?: cc.Rect): void {
        if (target instanceof cc.Node) {
            this.followNode = target;
        } else if (target instanceof cc.Vec2) {
            this.worldDest = target;
        }
        this.moveRaioMultiple = moveRaioMultiple;
        this.worldDest = null;
        if (offset) {
            this.followOffset = offset;
        }
        if (limitRect) {
            this.limitRect = limitRect;
        }
    }

    shakeTween: cc.Tween = null;
    /**开始相机震动 */
    startShake() {
        this.shakeTween = cc.tween(this.node)
            .repeatForever(
                cc.tween()
                    .by(this.shakeInterval, { x: this.shakeDist })
                    .by(this.shakeInterval, { x: -this.shakeDist })
            )
            .start()
    }
    /**停止相机震动 */
    stopShake() {
        if (this.shakeTween) {
            this.shakeTween.stop()
        }
    }
    /**
     *  单次震动
     * @param time 震动持续时间
     */
    shakeOnce(time: number = 1) {
        this.startShake();
        this.scheduleOnce(this.stopShake, time);
    }

    /**获取相机的投影尺寸 */
    getCameraViewRect(scale: number = 1): cc.Rect {
        const winSize = cc.view.getVisibleSize();
        let width = winSize.width / winSize.height * (this.dstOrthoHeight * 2) * scale;
        let height = this.dstOrthoHeight * 2 * scale;
        let wpos = this.getWpos(this.node)
        let curRect = cc.rect(
            wpos.x - width / 2,
            wpos.y - height / 2,
            width,
            height
        )
        return curRect;
    }

    moveDelta: cc.Vec2 = cc.v2(0, 0);
    followDst() {
        let ratio = this.dt * this.moveRaioMultiple;
        let dst = this.getWpos(this.node)
            .lerp(this.worldDest.add(this.followOffset), ratio)
        // dst.z = 1000;
        this.moveDelta = dst.clone().sub(this.getWpos(this.node))
        this.setWpos(this.node, dst)
    }
    update(dt: number) {
        this.dt = dt;
        if (this.isFollow) {
            if (this.followNode) {
                this.worldDest = this.getWpos(this.followNode)
            }
            if (this.worldDest) {
                // console.log('worldDest', this.worldDest)
                this.followDst();
            }

        }
        if (typeof this.cameraRatio == 'number') {
            this.zoomCameraTo();
        }
    }
    
    getWpos(node: (cc.Node | cc.Vec2 | cc.Vec3), isCentre: boolean = false): cc.Vec2 {
        let wpos;
        if (node instanceof cc.Node && node && node.isValid) {
            wpos = node.convertToWorldSpaceAR(cc.Vec2.ZERO);
            if (isCentre) {
                //计算中心点的位置
                let center = cc.v2();
                center.x = (0.5 - node.anchorX) * node.width;
                center.y = (0.5 - node.anchorY) * node.height;
                // console.log('center', center)
                wpos = node.convertToWorldSpaceAR(center);
            }
        }
        if (node instanceof cc.Vec2 || node instanceof cc.Vec3) {
            wpos = cc.v2(node);
        }
        return wpos;
    }
    setWpos(node: cc.Node, Wpos: cc.Vec2) {
        node.setPosition(node.parent.convertToNodeSpaceAR(Wpos));
    }
}
window['CameraController'] = CameraController;